﻿using System;
using Microsoft.Xna.Framework.Graphics;
using CymbergajTouch.Match;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace CymbergajTouch.Logic
{
    /// <summary>
    /// Class that represents statistics of single game between two players.
    /// </summary>
    class MatchScore : GoalHandler
    {
        //Basic
        private int leftScore = 0;
        private int rightScore = 0;
        private bool matchFinished = false;

        //Drawing score
        private SpriteFont scoreFont;
        private Vector2 scorePosition = new Vector2(20, 20);
        private readonly Color mainScoreColor = Color.White;
        private readonly Color secondScoreColor = Color.Black;
        private Color scoreColor = Color.White;

        //Score background
        private Texture2D backgroundTexture;

        //Goal scored animation
        private bool animateNewGoal = false;
        private const int newGoalAnimationDuration = 3 * 1000;
        private double newGoalAnimationEndsAt = 0;
        private const int oneColorDuration = 200;
        private double animationColorChangesAt = 0;

        //Arena sounds
        private double timeOfLastGoal = -1;
        private double timeOfLastArenaSound = -1;
        private double silenceTime = 10 * 1000;

        //XNA game time
        private double totalGameTime = 0;

        //Sound bank
        private SoundBank soundBank;
        private Cue arenaSound;

        //Options
        private Options options;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="options">match options</param>
        public MatchScore(Options options)
        {
            this.options = options;
        }

        /// <summary>
        /// Sets background texture for score.
        /// </summary>
        /// <param name="backgroundTexture">background texture</param>
        public void SetBackgroundTexture(Texture2D backgroundTexture)
        {
            this.backgroundTexture = backgroundTexture;
        }

        /// <summary>
        /// Sets sound bank for playing sound effects.
        /// </summary>
        /// <param name="soundBank">sound bank</param>
        public void SetSoundBank(SoundBank soundBank)
        {
            this.soundBank = soundBank;
        }

        /// <summary>
        /// Adds goal to one side.
        /// </summary>
        /// <param name="sender">sender object</param>
        /// <param name="left">true if left player scored, false otherwise</param>
        public void GoalScored(object sender, bool left)
        {
            if (options.Sound)
            {
                if (arenaSound != null)
                {
                    arenaSound.Stop(AudioStopOptions.Immediate);
                }
                soundBank.PlayCue("goal");
            }
            animateNewGoal = true;
            newGoalAnimationEndsAt = totalGameTime + newGoalAnimationDuration;
            animationColorChangesAt = totalGameTime + oneColorDuration;
            timeOfLastGoal = totalGameTime;

            if (left)
            {
                leftScore++;
            }
            else
            {
                rightScore++;
            }
        }

        /// <summary>
        /// Sets score font.
        /// </summary>
        /// <param name="scoreFont">score font</param>
        public void SetFont(SpriteFont scoreFont)
        {
            this.scoreFont = scoreFont;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            String score = " " + rightScore + ":" + leftScore;
            
            if (animateNewGoal)
            {
                score += " Goal!";

                if (totalGameTime >= animationColorChangesAt)
                {
                    if (scoreColor == mainScoreColor)
                    {
                        scoreColor = secondScoreColor;
                    }
                    else
                    {
                        scoreColor = mainScoreColor;
                    }
                    animationColorChangesAt = totalGameTime + oneColorDuration;
                }
            }

            if (matchFinished)
            {
                score += " (FINAL)";
            }

            score += " ";

            Vector2 scoreDimensions = scoreFont.MeasureString(score);
            Rectangle backgroundRectangle = new Rectangle((int)scorePosition.X, (int)scorePosition.Y, (int)scoreDimensions.X, (int)scoreDimensions.Y);
            spriteBatch.Draw(backgroundTexture, backgroundRectangle, null, new Color(Color.Black, 200));
            spriteBatch.DrawString(scoreFont, score, scorePosition, scoreColor);
        }

        /// <summary>
        /// Stops goal animation.
        /// </summary>
        private void StopNewGoalAnimation()
        {
            if (animateNewGoal)
            {
                if (totalGameTime >= (newGoalAnimationEndsAt + 0))
                {
                    animateNewGoal = false;
                    scoreColor = mainScoreColor;
                }
            }
        }

        /// <summary>
        /// Plays arena sounds.
        /// </summary>
        private void PlayArenaSounds()
        {
            if (!options.Sound)
            {
                return;
            }

            if (totalGameTime > timeOfLastGoal + silenceTime)
            {
                if (totalGameTime > timeOfLastArenaSound + silenceTime)
                {
                    if (arenaSound == null || !arenaSound.IsPlaying)
                    {
                        arenaSound = soundBank.GetCue("arena-sound-1");
                        arenaSound.Play();
                    }
                    timeOfLastArenaSound = totalGameTime;
                }
            }
        }

        public void Update(GameTime gameTime, bool paused)
        {
            totalGameTime = gameTime.TotalGameTime.TotalMilliseconds;

            //if it is first update, initialize times values
            if (timeOfLastGoal == -1 || timeOfLastArenaSound == -1)
            {
                timeOfLastGoal = totalGameTime;
                timeOfLastArenaSound = totalGameTime;
            }
            StopNewGoalAnimation();
            PlayArenaSounds();
        }

        /// <summary>
        /// Method used when game is finished.
        /// </summary>
        public void Finish()
        {
            animateNewGoal = false;
            scoreColor = mainScoreColor;
            if (options.Sound && arenaSound != null)
            {
                arenaSound.Stop(AudioStopOptions.Immediate);
            }
            matchFinished = true;
        }

        /// <summary>
        /// Checks if actual score is final score.
        /// </summary>
        /// <param name="goalsToWin"></param>
        /// <returns></returns>
        public bool IsMatchFinished(int goalsToWin)
        {
            if (leftScore >= goalsToWin || rightScore >= goalsToWin)
            {
                Finish();
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
